package pl.engine.camera
{
	import pl.engine.model.MapGrid;
	import pl.engine.model.Model;

	import starling.core.Starling;

	import flash.geom.Point;
	import flash.geom.Rectangle;

	/**
	 * ...
	 * @author Bakudo
	 */
	public class Camera
	{
		public static var SCREEN_W:uint = 7;
		public static var SCREEN_H:uint = 7;
		private static const DEGREE_TO_RAD_45:Number = 45 * Math.PI / 180;
		private static const DEGREE_TO_RAD_45_COS:Number = Math.cos( DEGREE_TO_RAD_45 );
		private static const DEGREE_TO_RAD_45_SIN:Number = Math.sin( DEGREE_TO_RAD_45 );
		private static const RAD_TO_DEGREE_45:Number = -45 * Math.PI / 180;
		private static const RAD_TO_DEGREE_45_COS:Number = Math.cos( RAD_TO_DEGREE_45 );
		private static const RAD_TO_DEGREE_45_SIN:Number = Math.sin( RAD_TO_DEGREE_45 );
		private static var viewRectangle:Rectangle;
		private static var position:Point;
		private static var _tilePosition:Point;
		private static var _iso:ICameraIsoParams;

		public static function init():void
		{
			position = new Point;
			_tilePosition = new Point;
			_iso = new Iso();
			viewRectangle = new Rectangle();
		}

		public static function updateScreenSize():void
		{
			var gs:Point = Model.getGridSize();
			if (gs.x < Camera.SCREEN_W)
			{
				//Camera.SCREEN_W = gs.x;
			}
			else
			{
				//Camera.SCREEN_W = Math.floor( Starling.current.stage.stageWidth / MapGrid.ISO_W )+3;
			}
			if (gs.y < Camera.SCREEN_H)
			{
				//Camera.SCREEN_H = gs.y;
			}
			else
			{
				//Camera.SCREEN_H = Math.floor( Starling.current.stage.stageHeight / MapGrid.ISO_H )+3;
			}
			Camera.SCREEN_W = 7;
			Camera.SCREEN_H = 7;
		}

		public static function convertIsoToRect( ix:Number, iy:Number ):Point
		{
			var px:Number = ix - MapGrid.ISO_W * .5;
			var py:Number = (iy - MapGrid.ISO_H * .5) * 2;
			var nx:Number = DEGREE_TO_RAD_45_COS * px - DEGREE_TO_RAD_45_SIN * py;
			var ny:Number = DEGREE_TO_RAD_45_SIN * px + DEGREE_TO_RAD_45_COS * py;
			return new Point( Math.floor( nx + MapGrid.TILE_W * .5 ), Math.floor( ny + MapGrid.TILE_H * .5 ) );
		}

		public static function convertRectToIso( rx:Number, ry:Number ):Point
		{
			var px:Number = rx - MapGrid.TILE_W * .5;
			var py:Number = ry - MapGrid.TILE_H * .5;
			var nx:Number = RAD_TO_DEGREE_45_COS * px - RAD_TO_DEGREE_45_SIN * py ;
			var ny:Number = RAD_TO_DEGREE_45_SIN * px + RAD_TO_DEGREE_45_COS * py ;
			return new Point( Math.floor( MapGrid.ISO_W * .5 + nx ), Math.floor( MapGrid.ISO_H * .5 + ny * .5 ) );
		}

		public static function lookAtTileCenter( tx:uint, ty:uint ):void
		{
			var px:Number = (tx * MapGrid.TILE_W) + MapGrid.TILE_W * .5;
			var py:Number = (ty * MapGrid.TILE_H) + MapGrid.TILE_H * .5;

			var p:Point = convertRectToIso( px, py );

			iso.x = p.x;
			iso.y = p.y;
		}

		public static function isInViewRange( tileoX:uint, tileoY:uint ):Boolean
		{
			var gridW:uint = MapGrid.GRID_W_COUNT;
			var gridH:uint = MapGrid.GRID_H_COUNT;
			var tilePos:Point = Camera.tilePosition;
			var halfScreenW:uint = Math.floor( Camera.SCREEN_W * .5 );
			var halfScreenH:uint = Math.floor( Camera.SCREEN_H * .5 );
			var ox:uint;
			var oy:uint;

			// ox
			if (tilePos.x >= (gridW - halfScreenW))
				ox = gridW - 1;
			else if (tilePos.x < halfScreenW)
				ox = Camera.SCREEN_W - 1;
			else
				ox = tilePos.x + halfScreenW;

			// oy
			if (tilePos.y < halfScreenH )
				oy = 0;
			else if (tilePos.y >= (gridH - halfScreenH))
				oy = gridH - Camera.SCREEN_H;
			else
				oy = tilePos.y - halfScreenH;

			var dimX:uint = (ox - Camera.SCREEN_W) < 0 ? ox + 1 : Camera.SCREEN_W;
			var dimY:uint = (oy + Camera.SCREEN_H) < gridH ? Camera.SCREEN_H : gridH - oy;

			var rect:Rectangle = new Rectangle();

			rect.width = dimX;
			rect.height = dimY;
			rect.x = ox - dimX + 1;
			rect.y = oy;
			if (rect.contains( tileoX, tileoY )) return true;

			return false;
		}

		// przesuwanie po x w normalnym ukladzie wspolrzednych mapowane jest na
		// izometryczny uklad wspolrzednych
		public static function get tileX():uint
		{
			return _tilePosition.x;
		}

		public static function get tileY():uint
		{
			return _tilePosition.y;
		}

		public static function get tilePosition():Point
		{
			var rectPos:Point = convertIsoToRect( iso.x, iso.y );
			rectPos.x = rectPos.x < 0 ? 0 : rectPos.x;
			rectPos.y = rectPos.y < 0 ? 0 : rectPos.y;
			_tilePosition.x = Math.floor( rectPos.x / MapGrid.TILE_W );
			_tilePosition.y = Math.floor( rectPos.y / MapGrid.TILE_H );
			return _tilePosition;
		}

		public static function info():void
		{
			// trace( 'Camera:\nx:', x + '\ny:', y + '\ntileX:', tileX + '\ntileY:', tileY + '\n---------------' );
		}

		public static function get iso():ICameraIsoParams
		{
			return _iso;
		}

		public static function get rectPos():Point
		{
			return convertIsoToRect( iso.x, iso.y );
		}
	}
}
import pl.engine.camera.ICameraIsoParams;

import flash.geom.Point;

class Iso implements ICameraIsoParams
{
	private var position:Point = new Point();

	public function set x( val:Number ):void
	{
		position.x = val;
	}

	public function get x():Number
	{
		return position.x;
	}

	public function set y( val:Number ):void
	{
		position.y = val;
	}

	public function get y():Number
	{
		return position.y;
	}
}
